package com.cloud.es.controller;

import com.alibaba.fastjson.JSON;
import com.cloud.es.config.ElasticSearchConfig;
import com.cloud.es.entity.Account;
import com.cloud.es.entity.SearchParam;
import com.cloud.es.entity.SearchResult;
import com.cloud.es.entity.User;
import com.cloud.es.service.ProductSearchService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.SearchService;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.Avg;
import org.elasticsearch.search.aggregations.metrics.AvgAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/es/data")
@Slf4j
public class EsDataController {
    @Autowired
    private RestHighLevelClient client;
    @Autowired
    private ProductSearchService productSearchService;

    @SneakyThrows
    @RequestMapping("/save")
    public void saveUser() {
        IndexRequest indexRequest = new IndexRequest("user");
        indexRequest.id("1");   //数据的id
        // KV 键值对
        // indexRequest.source("userName","zhangsan","age",18,"gender","男");
        User user = new User();
        user.setUserName("zhangsan");
        user.setAge(18);
        user.setGender("男");

        String jsonString = JSON.toJSONString(user);
        indexRequest.source(jsonString, XContentType.JSON);  //要保存的内容
        // 同步执行
        client.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);

    }

    @SneakyThrows
    @RequestMapping("/bashSave")
    public void bashSave() {
        BulkRequest bulkRequest = new BulkRequest();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setUserName("zhangsan");
            user.setAge(i);
            user.setGender("男");
            //构造保存请求
            IndexRequest indexRequest = new IndexRequest("user");
            String jsonString = JSON.toJSONString(user);
            indexRequest.source(jsonString, XContentType.JSON);  //要保存的内容
            bulkRequest.add(indexRequest);
        }
        // 同步执行
        client.bulk(bulkRequest, ElasticSearchConfig.COMMON_OPTIONS);

    }

    @SneakyThrows
    @RequestMapping("/saveAccount")
    public void saveAccount() {
        List<Account> objects = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Account account = new Account();
            account.setAge(i * 10);
            account.setBalance(i * 100);
            account.setAddress("mall" + i);
            account.setName("zhang" + i);
            objects.add(account);
        }
        for (int i = 0; i < 5; i++) {
            Account account = new Account();
            account.setAge(i * 10);
            account.setBalance(i * 100);
            account.setAddress("mall");
            account.setName("zhang" + i);
            objects.add(account);
        }
        Account account1 = new Account();
        account1.setAge(10);
        account1.setBalance(500);
        account1.setAddress("大连");
        account1.setName("李四");

        Account account2 = new Account();
        account2.setAge(20);
        account2.setBalance(1000);
        account2.setAddress("mall");
        account2.setName("王五");

        objects.add(account1);
        objects.add(account2);

        for (Account account : objects) {
            IndexRequest indexRequest = new IndexRequest("account");
            String jsonString = JSON.toJSONString(account);
            indexRequest.source(jsonString, XContentType.JSON);
            client.index(indexRequest, ElasticSearchConfig.COMMON_OPTIONS);
        }

    }


    @SneakyThrows
    @RequestMapping("/getData")
    public String getData() {
        // 检索地址中带有 mill 的人员年龄分布和平均薪资
        // 1. 创建检索请求
        SearchRequest searchRequest = new SearchRequest();
        // 指定索引
        searchRequest.indices("account");
        // 指定 DSL 检索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 1.1 构建检索条件 address 包含 mall
        searchSourceBuilder.postFilter(QueryBuilders.matchQuery("address", "mall"));
        // 1.2 按照年龄值分布进行聚合
        TermsAggregationBuilder ageAgg = AggregationBuilders.terms("ageAgg").field("age").size(6);
        searchSourceBuilder.aggregation(ageAgg);
        // 1.3 计算平均薪资
        AvgAggregationBuilder balanceAvg = AggregationBuilders.avg("balanceAvg").field("balance");
        searchSourceBuilder.aggregation(balanceAvg);

        System.out.println("检索条件：" + searchSourceBuilder.toString());
        searchRequest.source(searchSourceBuilder);

        // 2. 执行检索, 获得响应
        SearchResponse searchResponse = client.search(searchRequest, ElasticSearchConfig.COMMON_OPTIONS);

        System.out.println(JSON.toJSONString(searchResponse));
        // 3. 分析结果
        // 3.1 获取所有查到的记录
        SearchHits hits = searchResponse.getHits();
        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) {
            // 数据字符串
            String jsonString = hit.getSourceAsString();
            System.out.println(jsonString);
            // 可以通过 json 转换成实体类对象
             Account account = JSON.parseObject(jsonString, Account.class);
        }

        // 3.2 获取检索的分析信息(聚合数据等)
        Aggregations aggregations = searchResponse.getAggregations();
        // for (Aggregation aggregation : aggregations.asList()) {
        //     System.out.println("当前聚合名：" + aggregation.getName());
        // }
        Terms ageAgg1 = aggregations.get("ageAgg");
        for (Terms.Bucket bucket : ageAgg1.getBuckets()) {
            String keyAsString = bucket.getKeyAsString();
            System.out.println("年龄：" + keyAsString + " 岁的有 " + bucket.getDocCount() + " 人");
        }

        Avg balanceAvg1 = aggregations.get("balanceAvg");
        System.out.println("平均薪资: " + balanceAvg1.getValue());
        return null;
    }

    @SneakyThrows
    @RequestMapping("/complexQuery")
    public void complexQuery() {
        // 优先对索引进行创建，数据插入
        SearchParam param = new SearchParam();
        SearchResult result = productSearchService.search(param);
    }
}
